package com.wtf.dsp.admin.core.dao;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.wtf.dsp.admin.entity.WtfDspDbConfig;
import com.wtf.dsp.admin.enums.CommonErrorEnum;
import com.wtf.dsp.admin.exception.WtfDspException;
import com.wtf.dsp.admin.mapper.WtfDspDbConfigMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * ClassName: DbGeneratorDao
 * Description:
 * date: 2024/9/6 10:17
 *
 * @author linhuanyou
 * @version 1.0
 */
@Slf4j
public class DbJdbcGeneratorDao extends AbstractJdbcDao implements InitializingBean {

    private WtfDspDbConfigMapper wtfDspDbConfigMapper;

    protected ConcurrentMap<String, WtfDspDbConfig> dbConfigs = new ConcurrentHashMap<String, WtfDspDbConfig>();

    private Thread refreshThread;

    private int refreshTime = 1;


    private volatile long exceTime ;

    private volatile boolean toStop = false;

    private volatile boolean frist = false;

    public DbJdbcGeneratorDao(JdbcTemplate jdbcTemplate, WtfDspDbConfigMapper wtfDspDbConfigMapper) {
        super(jdbcTemplate);
        this.wtfDspDbConfigMapper = wtfDspDbConfigMapper;
    }

    @Override
    protected String dbDriver(String db){
        return getDriver(db);
    }

    @Override
    protected String jdbcUrl(String db, String host, Integer port, String dbName) {
        return String.format(getJdbcUrl(db),host, port, dbName);
    }

    @Override
    public String getJdbcUrl(String db) {
        WtfDspDbConfig dbConfig = getDbConfig(db);
        return dbConfig.getJdbcUrl();
    }

    private WtfDspDbConfig getDbConfig(String db){
        if(!dbConfigs.containsKey(db)){
            throw new WtfDspException(CommonErrorEnum.DB_CONFIG_ERROR);
        }
        return dbConfigs.get(db);
    }

    @Override
    public String getDriver(String db){
        checkDriver(getDbConfig(db).getDriverClass());
        return dbConfigs.get(db).getDriverClass();
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        refreshDbConfig();
        start();
    }

    private void refreshDbConfig() {
        QueryWrapper<WtfDspDbConfig> wtfDspDbConfigQueryWrapper = new QueryWrapper<>();
        Map<String, WtfDspDbConfig> wtfDspDbConfigs = wtfDspDbConfigMapper.selectList(wtfDspDbConfigQueryWrapper).stream().collect(Collectors.toMap(WtfDspDbConfig::getDb, Function.identity()));
        this.dbConfigs.putAll(wtfDspDbConfigs);
    }


    public void start(){
        this.exceTime = System.currentTimeMillis();
        refreshThread = new Thread(new Runnable() {
            @Override
            public void run() {
                while (!toStop) {
                    if(frist){
                        try {
                            long now = System.currentTimeMillis();
                            if(now -  exceTime >= (refreshTime * 1000L * 60) ){
                                log.info(">>>>>>>>>>> Wtf Dsp Db Config Thread Executor Begin Time >>>> :{}", DateUtil.formatDateTime(new Date(now)));
                                exceTime = now;
                                refreshDbConfig();
                                log.info(">>>>>>>>>>> Wtf Dsp Db Config Thread Executor Success Time >> :{}",DateUtil.formatDateTime(new Date()));
                            }
                        } catch (Exception e) {
                            if (!toStop) {
                                log.error(">>>>>>>>>>> Wtf Dsp Db Config monitor thread error  :{}", e);
                            }
                        }
                    } else {
                        frist = true;
                        log.error(">>>>>>>>>>> Wtf Dsp Db Config monitor thread start :{}", frist);
                    }
                    try {
                        TimeUnit.SECONDS.sleep(refreshTime * 30L);
                    } catch (InterruptedException e) {
                        if (!toStop) {
                            log.error(">>>>>>>>>>> Wtf Dsp Db Config monitor thread error:{}", e);
                        }
                    }
                }
                log.info(">>>>>>>>>>> Wtf Dsp Db Config thread stop : {}",frist);
            }
        });
        refreshThread.setDaemon(true);
        refreshThread.setName("Wtf Dsp Db Config Monitor");
        refreshThread.start();
    }
}
